package com.ylx.code.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ylx.code.bo.ConnectMarkBo;
import com.ylx.code.bo.MarkListBo;
import com.ylx.code.bo.NewScanRecordBo;
import com.ylx.code.bo.RecordListBo;
import com.ylx.code.enums.CommonEnum;
import com.ylx.code.mapper.MarkInfoMapper;
import com.ylx.code.model.MarkInfo;
import com.ylx.code.model.MarkScanRecord;
import com.ylx.code.service.MarkInfoService;
import com.ylx.code.service.MarkScanRecordService;
import com.ylx.code.vo.MarkScanRecordVo;
import com.ylx.code.vo.MarkVo;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 商户表接口实现
 *
 * @author yanglixin
 * date    2023-10-17 16:36:07
 */
@Service
@AllArgsConstructor
public class MarkInfoServiceImpl extends ServiceImpl<MarkInfoMapper, MarkInfo> implements MarkInfoService {

    private final MarkScanRecordService markScanRecordService;

    @Override
    public MarkVo createCode() {
        MarkInfo markInfo = new MarkInfo();
        markInfo.setCreateTime(new Date());
        this.save(markInfo);
        return BeanUtil.copyProperties(markInfo, MarkVo.class);
    }

    @Override
    public MarkVo connectMark(ConnectMarkBo bo) {
        MarkInfo byName = this.getByName(bo.getMarkName(), null);
        if (Objects.nonNull(byName)) {
            throw new RuntimeException("当前商户已绑定二维码");
        }
        MarkInfo markInfo = this.getById(bo.getId());
        if (Objects.isNull(markInfo)) {
            throw new RuntimeException("二维码不存在");
        }
        if (Objects.equals(markInfo.getCreateStatus(), CommonEnum.TRUE.getValue())) {
            throw new RuntimeException(String.format("当前二维码已绑定商户: %s",markInfo.getMarkName()));
        }
        markInfo.setMarkName(bo.getMarkName());
        markInfo.setCreateStatus(CommonEnum.TRUE.getValue());
        this.updateById(markInfo);
        return BeanUtil.copyProperties(markInfo, MarkVo.class);
    }

    @Override
    public MarkVo markInfo(Long id) {
        MarkInfo markInfo = this.getById(id);
        if (Objects.isNull(markInfo)) {
            throw new RuntimeException("商户不存在");
        }
        MarkVo markVo = BeanUtil.copyProperties(markInfo, MarkVo.class);
        //查询扫描记录
        List<MarkScanRecord> markScanRecords = markScanRecordService.getByMarkId(id);
        if (CollectionUtil.isNotEmpty(markScanRecords)) {
            markVo.setRecordVos(BeanUtil.copyToList(markScanRecords, MarkScanRecordVo.class));
        }
        return markVo;
    }

    @Override
    public Page<MarkVo> markList(MarkListBo bo) {
        LambdaQueryWrapper<MarkInfo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(MarkInfo::getIsDeleted, CommonEnum.UN_DELETE.getValue());
        wrapper.orderByDesc(MarkInfo::getId);
        wrapper.like(StrUtil.isNotBlank(bo.getMarkName()), MarkInfo::getMarkName,bo.getMarkName());
        wrapper.eq(Objects.nonNull(bo.getCreateStatus()), MarkInfo::getCreateStatus,bo.getCreateStatus());

        Page<MarkInfo> page = Page.of(bo.getCurrent(),bo.getSize());
        page = this.page(page, wrapper);
        Page<MarkVo> result = Page.of(bo.getCurrent(),bo.getSize());
        result.setTotal(page.getTotal());
        List<MarkInfo> records = page.getRecords();
        if (CollectionUtil.isNotEmpty(records)) {
            List<MarkVo> markVos = records.stream().map(record -> {
                MarkVo markVo = BeanUtil.copyProperties(record, MarkVo.class, "createTime");
                markVo.setCreateTime(DateUtil.formatDateTime(record.getCreateTime()));
                return markVo;
            }).collect(Collectors.toList());
            result.setRecords(markVos);
        }
        return result;
    }

    @Override
    public void deleteMark(Long id) {
        this.removeById(id);
    }

    @Override
    public MarkScanRecordVo newScanRecord(NewScanRecordBo bo) {
        MarkScanRecord markScanRecord = BeanUtil.copyProperties(bo, MarkScanRecord.class);
        markScanRecord.setCreateTime(new Date());
        markScanRecordService.save(markScanRecord);
        //扫描参数加一
        LambdaUpdateWrapper<MarkInfo> wrapper = Wrappers.lambdaUpdate();
        wrapper.eq(MarkInfo::getId,bo.getMarkId());
        wrapper.setSql("scan_number = scan_number+1");
        this.update(wrapper);
        return BeanUtil.copyProperties(markScanRecord,MarkScanRecordVo.class);
    }

    @Override
    public Page<MarkScanRecordVo> scanRecordList(RecordListBo bo) {
        Page<MarkScanRecordVo> result = Page.of(bo.getCurrent(),bo.getSize());
        LambdaQueryWrapper<MarkInfo> markWrapper = Wrappers.lambdaQuery();
        markWrapper.eq(MarkInfo::getIsDeleted, CommonEnum.UN_DELETE.getValue());
        markWrapper.like(StrUtil.isNotBlank(bo.getMarkName()), MarkInfo::getMarkName,bo.getMarkName());
        List<MarkInfo> markInfoList = this.list(markWrapper);
        Set<Long> markIds;
        if (CollectionUtil.isEmpty(markInfoList)) {
            return result;
        } else {
            markIds = markInfoList.stream().map(MarkInfo::getId).collect(Collectors.toSet());
        }

        LambdaQueryWrapper<MarkScanRecord> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(MarkScanRecord::getIsDeleted, CommonEnum.UN_DELETE.getValue());
        wrapper.orderByDesc(MarkScanRecord::getId);
        wrapper.like(StrUtil.isNotBlank(bo.getRemark()), MarkScanRecord::getRemark,bo.getRemark());
        wrapper.ge(Objects.nonNull(bo.getCreateStartTime()), MarkScanRecord::getCreateTime,bo.getCreateStartTime());
        wrapper.le(Objects.nonNull(bo.getCreateEntTime()), MarkScanRecord::getCreateTime,bo.getCreateEntTime());
        wrapper.in(CollectionUtil.isNotEmpty(markIds), MarkScanRecord::getMarkId,markIds);

        Page<MarkScanRecord> page = Page.of(bo.getCurrent(),bo.getSize());
        page = markScanRecordService.page(page,wrapper);
        List<MarkScanRecord> records = page.getRecords();

        result.setTotal(page.getTotal());
        if (CollectionUtil.isNotEmpty(records)) {
            List<MarkScanRecordVo> markScanRecordVos = records.stream().map(record -> {
                MarkScanRecordVo vo = BeanUtil.copyProperties(record, MarkScanRecordVo.class, "createTime");
                vo.setCreateTime(DateUtil.formatDateTime(record.getCreateTime()));
                return vo;
            }).collect(Collectors.toList());
            List<MarkInfo> markInfos = this.listByIds(records.stream().map(MarkScanRecord::getMarkId).collect(Collectors.toList()));
            if (CollectionUtil.isNotEmpty(markInfos)) {
                Map<Long, MarkInfo> markInfoMap = markInfos.stream().collect(Collectors.toMap(MarkInfo::getId, m -> m));
                for (MarkScanRecordVo recordVo : markScanRecordVos) {
                    Long markId = recordVo.getMarkId();
                    MarkInfo markInfo = markInfoMap.get(markId);
                    if (Objects.nonNull(markInfo)) {
                        recordVo.setMarkName(markInfo.getMarkName());
                    }
                }
            }
            result.setRecords(markScanRecordVos);
        }
        return result;
    }

    @Override
    public MarkInfo getByName(String markName, Long id) {
        LambdaQueryWrapper<MarkInfo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(MarkInfo::getMarkName,markName);
        wrapper.ne(Objects.nonNull(id), MarkInfo::getId,id);
        wrapper.eq(MarkInfo::getIsDeleted, CommonEnum.UN_DELETE.getValue());
        return this.getOne(wrapper);
    }

    @Override
    public void deleteRecord(Long id) {
        markScanRecordService.removeById(id);
    }
}